<?php

namespace App\Models\Plane\Airports\Repositories;

use App\Models\Plane\Airports\Airport;
use App\Models\Plane\Airports\Repositories\Interfaces\AirportRepositoryInterface;
use App\Trip\Repository\BaseRepository;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;

class AirportRepository extends BaseRepository implements AirportRepositoryInterface
{
    public function __construct(Airport $model)
    {
        parent::__construct($model);
    }

    public function addAirport(array $data): Airport
    {
        if ($airport = $this->findOneByCode($data['code'])) {
            $this->update($data, $airport);
            return $airport;
        }
        return $this->create($data);
    }

    public function findOneByCode(string $air_code): ?Airport
    {
        $cache_key_code = "Airport:Code:{$air_code}";
        if (Cache::has($cache_key_code)) {
            return Cache::get($cache_key_code);
        }
        $airport = $this->findOneBy([
            'code' => $air_code,
        ]);
        $ct      = 30 * config('trip.ttl.day');
        if (!$airport) {
            $ct = 30 * config('trip.ttl.minutes');
        }
        Cache::put($cache_key_code, $airport, $ct);
        return $airport;

    }

    public function delByCode(string $air_code): bool
    {
        return $this->findOneByCode($air_code)?->delete() ?: false;
    }

    public function updateAirport(Airport $airport, array $data): bool
    {
        return $this->update($data, $airport);
    }


    /**
     * @inheritDoc
     */
    public function listStations($condition = []): Collection
    {
        return $this->model
            ->where(function ($q) use ($condition) {
                if (isset($condition['city_code']) && $condition['city_code']) {
                    $wh = is_array($condition['city_code']) ? 'whereIn' : 'where';
                    $q->$wh('city_code', $condition['city_code']);
                }
            })
            ->get();
    }

    /**
     * @param string $name
     * @return Airport|null
     */
    public function findOneByName(string $name): ?Airport
    {
        $cache_key_code = "Airport:Name:{$name}";
        if (Cache::has($cache_key_code)) {
            return Cache::get($cache_key_code);
        }
        $airport = $this->findOneBy([
            'name' => $name,
        ]);
        $ct      = 30 * config('trip.ttl.day');
        if (!$airport) {
            $ct = 30 * config('trip.ttl.minutes');
        }
        Cache::put($cache_key_code, $airport, $ct);
        return $airport;
    }

    /**
     * @param int $limit
     * @return Collection
     */
    public function listHotAirports(int $limit = 6): Collection
    {
        return $this->model->where('hot', 1)
                           ->orderByDesc('sorts')
                           ->limit($limit)
                           ->get([
                               'sorts',
                               'name',
                               'name_uy',
                               'code',
                               'city_code',
                           ]);
    }

    /**
     * @param int $limit
     * @return Collection
     */
    public function listHotCities(int $limit = 6): Collection
    {
        return $this->model->where('hot', 1)
                           ->limit($limit)
                           ->select([
                               'city_code',
                           ])
                           ->selectRaw("SUM(sorts) as sorts")
                           ->groupBy('city_code')
                           ->orderByDesc('sorts')
                           ->get();
    }

    public function findOneByCityCode(string $city_code): ?Airport
    {
        $cache_key_code = "Airport:CityCode:{$city_code}";
        if (Cache::has($cache_key_code)) {
            return Cache::get($cache_key_code);
        }
        $airport = $this->findOneBy([
            'city_code' => $city_code,
        ]);
        $ct      = 30 * config('trip.ttl.day');
        if (!$airport) {
            $ct = 30 * config('trip.ttl.minutes');
        }
        Cache::put($cache_key_code, $airport, $ct);
        return $airport;
    }
}